package binaryTree;

import org.junit.BeforeClass;
import org.junit.Test;
import static org.junit.Assert.*;
import org.junit.Before;
import java.util.*;
/**
 * Created by anatolii.bondarenko on 2/3/14.
 */
public class testNode {
    private Node node;
    private Node node1;
    private Node node2;
    private Node node3;
    private Node node4;
    private Node node5;
    private Node node6;
    private Node node7;
    private Node node8;
    private Node node9;
    private boolean isRoot = true;
    private String name = "0";
    private String name1 = "1";
    private String name2 = "2";
    private String name3 = "3";
    private String name4 = "4";
    private String name5 = "5";
    private String name6 = "6";
    private String name7 = "7";
    private String name8 = "8";
    private String name9 = "9";

    @Before
    public void initNodes(){
        node = new Node(name);
        node1 = new Node(name1);
        node2 = new Node(name2);
        node3 = new Node(name3);
        node4 = new Node(name4);
        node5 = new Node(name5);
        node6 = new Node(name6);
        node7 = new Node(name7);
        node8 = new Node(name8);
        node9 = new Node(name9);
    }

    @Test
    public void testGetName(){
        assertEquals(node.getName(), name);
    }

    @Test
    public void testAddLeftChild(){
        node.addLeft(node1);
        assertEquals(node.getLeft(), node1);
    }

    @Test
    public void testAddRightChild(){
        node.addRight(node1);
        assertEquals(node.getRight(), node1);
    }

    @Test
    public void testAddLeftChildWithExistingLeftChild(){
        node.addLeft(node1);
        node.addLeft(node2);
        assertEquals(node.getLeft(), node2);
        assertEquals(node2.getLeft(),node1);
    }

    @Test
    public void testAddRightChildWithExistingRightChild(){
        node.addRight(node1);
        node.addRight(node2);
        assertEquals(node.getRight(), node2);
        assertEquals(node2.getRight(),node1);
    }

    @Test
    public void testRemoveRootNode(){
        node.addLeft(node1);
        Node.removeNode(node);
        assertTrue(node1.isRoot());
        node1.addLeft(node2);
        Node.removeNode(node1);
        assertTrue(node2.isRoot());
    }

    @Test
    public void testRemoveNodeWithoutChildren(){
        node.addLeft(node1);
        Node.removeNode(node1);
        assertEquals(node.getLeft(), null);
        initNodes();
        node.addRight(node1);
        Node.removeNode(node1);
        assertEquals(node.getRight(), null);
    }

    @Test
    public void testRemoveNodeWithOneChild(){
        // Removing left node with left child will set left child to place of it's parent(left)
        node.addLeft(node1);
        node1.addLeft(node2);
        Node.removeNode(node1);
        assertEquals(node.getLeft(), node2);
        // Removing left node with right child will set left child to place of it's parent(left)
        initNodes();
        node.addLeft(node1);
        node1.addRight(node2);
        Node.removeNode(node1);
        assertEquals(node.getLeft(), node2);
        // Removing right node with left child will set left child to place of it's parent(right)
        initNodes();
        node.addRight(node1);
        node1.addLeft(node2);
        Node.removeNode(node1);
        assertEquals(node.getRight(), node2);
        // Removing right node with left child will set right child to place of it's parent(right)
        initNodes();
        node.addRight(node1);
        node1.addRight(node2);
        Node.removeNode(node1);
        assertEquals(node.getRight(), node2);
    }

    @Test
    public void testRemoveNodeImpossibleWithTwoChildren(){
        node.addLeft(node1);
        node1.addLeft(node2);
        node1.addRight(node3);
        Node.removeNode(node1);
        assertEquals(node.getLeft(), node1);
        initNodes();
        node.addRight(node1);
        node1.addLeft(node2);
        node1.addRight(node3);
        Node.removeNode(node1);
        assertEquals(node.getRight(), node1);
    }

    @Test
    public void testGetHeightOfTheTreeAfterLinearAddingNodes(){
        node.addLeft(node1);
        node1.addRight(node2);
        node2.addLeft(node3);
        assertTrue(Node.getHeightOfTheTree()==4);
    }

    @Test
    public void testGetHeightOftheTreeAfterBranchedAddingOfNodes(){
        node.addLeft(node1);
        node.addRight(node2);
        node1.addLeft(node3);
        assertTrue(Node.getHeightOfTheTree()==3);
    }
    @Test
    public void testGetHeightOfTheTreeAfterReducingNode(){
        node.addLeft(node1);
        node.addRight(node2);
        node1.addLeft(node3);
        node2.addLeft(node4);
        node2.addRight(node5);
        node3.addLeft(node6);
        node3.addRight(node7);
        node4.addRight(node8);
        node8.addLeft(node9);
        Node.removeNode(node4);
        assertTrue(Node.getHeightOfTheTree()==4);
    }

    @Test
    public void testGetHeightOfTheTreeAfterReducingNodeFromNotTheDeepestBranch(){
        node.addLeft(node1);
        //node.addRight(node2);
        node1.addLeft(node3);
        //node2.addLeft(node4);
        //node2.addRight(node5);
        node3.addLeft(node6);
        node3.addRight(node7);
        //node4.addRight(node8);
        //node8.addLeft(node9);
        Node.removeNode(node1);
        assertTrue(Node.getHeightOfTheTree()==3);
    }

    @Test
    public void testGetHeightOfTheTreeAfterReducingSeveralNodesFromDifferentBranches(){
        node.addLeft(node1);
        node.addRight(node2);
        node1.addLeft(node3);
        node2.addLeft(node4);
        node2.addRight(node5);
        node3.addLeft(node6);
        node3.addRight(node7);
        node4.addRight(node8);
        node8.addLeft(node9);
        assertTrue(Node.getHeightOfTheTree()==5);
        Node.removeNode(node8);
        assertTrue(Node.getHeightOfTheTree()==4);
        Node.removeNode(node1);
        assertTrue(Node.getHeightOfTheTree()==4);
        Node.removeNode(node4);
        assertTrue(Node.getHeightOfTheTree()==3);
        Node.removeNode(node9);
        assertTrue(Node.getHeightOfTheTree()==3);
    }
}
